
#include <cassert>
#include <windows.h>
#include <vector>
#include "directory.h"
#include "path.h"

using namespace fs;

struct DirectoryIterator::Impl {
	std::vector<DirectoryEntry> entries;
	size_t pos;
};

DirectoryEntry::DirectoryEntry( const std::string & name )
{
	_name = name;
}

std::string DirectoryEntry::name()
{
	return _name;
}

bool DirectoryEntry::operator==( const DirectoryEntry & other ) const
{
	return _name == other._name;
}

DirectoryIterator::DirectoryIterator(): _pimpl(0)
{

}

DirectoryIterator::DirectoryIterator( const Path & dir ) : _pimpl( new Impl )
{
	assert( dir.is_directory() );

	WIN32_FIND_DATAA find_data;
	std::string filter = dir.as_string() + "\\*.*";

	HANDLE handle = ::FindFirstFileA( filter.c_str(), &find_data );
	BOOL found = FALSE;
	if( handle != INVALID_HANDLE_VALUE )
	{
		do {
			DirectoryEntry entry( find_data.cFileName );
			_pimpl->entries.push_back( entry );
			found = ::FindNextFileA( handle, &find_data );
		} while( found );
	}
	FindClose(handle);

	_pimpl->pos = 0;
}

DirectoryIterator &DirectoryIterator::operator++()
{
	if( _pimpl->pos + 1 < _pimpl->entries.size() )
	{
		++_pimpl->pos;
		return *this;
	}
	else 
	{
		//return DirectoryIterator();
		delete _pimpl;
		_pimpl = 0;
		return *this;
	}
}

DirectoryEntry &DirectoryIterator::operator*()
{
	return _pimpl->entries[_pimpl->pos];
}

DirectoryEntry* DirectoryIterator::operator->()
{
	return &_pimpl->entries[_pimpl->pos];
}

bool DirectoryIterator::operator ==( const DirectoryIterator& other ) const
{
	return _pimpl == other._pimpl 
		|| ( _pimpl != 0 && other._pimpl != 0 
		&& _pimpl->pos == other._pimpl->pos && _pimpl->entries == other._pimpl->entries );
}

bool DirectoryIterator::operator !=( const DirectoryIterator& other ) const
{
	return !operator==( other );
}
